// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: declaration of CFormControl.
//   $Id$



// FormControl.h: interface for the CFormControl class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_FORMCONTROL_H__81D997E7_782B_4D83_95B2_34EA58BEFA7E__INCLUDED_)
#define AFX_FORMCONTROL_H__81D997E7_782B_4D83_95B2_34EA58BEFA7E__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

//#include "inetFunc.h"
#include "Impl.h"
#include "ImplInterfaces.h"
#include "events.h"
#include <DOM3XPath.h>
#include "QName.h"
#include "BindingTarget.h"
#include "IUIEvents.h"
typedef IXMLDOMNode CNode;
struct IDOMEvent;

//struct IXPathResult;

class CXFormsXFormsElement;
class CImplModel;
class CImplAction;
class CXFormsParseContent;

class CXFormsElement;
class CXFormsParse;
class CDOM3Document;
class CIdResolver;
class CImplContent;
class CImplInstance;

class CXFormsParseFormControl;




class CFormControl 
	: public CImpl
	//interface to make this class available to CBoundNode	
	,public IBindingTarget
	//, public IItemWithCaption
{
	friend class CXFormsParseFormControl;
public:
	CFormControl();
	CFormControl(CXFormsElement* pElement);



//	virtual HRESULT GetContextNode(CImplModel** ppModel, CNode** ppContextNode, ULONG ulOffset);
//	HRESULT getModelName(BSTR* psName);
	virtual HRESULT init(CImpl * pParent);
	//Do Nothing, only bound form controls build dependencies.
	virtual void buildDependencies(){};

	// Moved to CFormControl as part of bug 459
	void SetControlType(const wchar_t * const lpwszControlType);
	inline BSTR GetControlType(void) const;

	inline HRESULT initialize(bool bForce);
	//This should be pure virtual?
	virtual HRESULT refresh();
	
//	HRESULT revalidate();
	HRESULT setFocus(); 
	
	inline HRESULT getNavIndex(BSTR * pszVal);
	inline HRESULT getAccessKey(BSTR * pszVal);
	inline HRESULT getIncremental(BOOL * pszIncremental);
		
		//XForms events
//Not all of these are required
	
	virtual HRESULT onhelp();
	virtual HRESULT onhint();
	virtual HRESULT onnext();
	virtual HRESULT onprevious();

	virtual HRESULT onvaluechanging();
	
	//These are not form control events, they belong
	//	to a specific set of elements.
	virtual HRESULT ondeselect(); 
	virtual HRESULT onselect();



	virtual HRESULT onfocus();

	virtual HRESULT onDOMFocusIn();
	virtual HRESULT onDOMFocusOut();
	

	virtual HRESULT onactivate();
	//to replace the current erroneous usage of onvaluechanged
	virtual HRESULT putValue(BSTR const  sVal);
	
	//Events from IBindingTarget:
	//	These are dispatched in response
	//	to changes in state in the DOM
	virtual HRESULT oninvalid();
	virtual HRESULT onvalid();
	virtual HRESULT onreadonly();
	virtual HRESULT onreadwrite();
	virtual HRESULT onrequired();
	virtual HRESULT onoptional();
	virtual HRESULT onenabled();
	virtual HRESULT ondisabled();
	virtual HRESULT onvaluechanged();
	virtual void disconnect(CBoundNode * /*pNode*/){};
	// Sets the inital state of the target in one call to IHTMLElement::put_className() which 
	// results in better performance on start up.
	virtual HRESULT setInitalState(bool bEnabled, bool bReadOnly, bool bValid, bool bRequired);
	virtual void bindingToNode(bool bBinding);

	virtual void notifyDelete();
	virtual void setModel(CImplModel*  pModel);
	bool m_bInitializeDone;
	virtual HRESULT blank();

	// called by the front-end control when a 
	//	given value can be displayed.
	virtual HRESULT onInRange(void);
	// called by the front-end control when a 
	//	given value can't be displayed.
	virtual HRESULT onOutOfRange(void);

	inline bool isLateInitalisedControl();

	inline bool InRange(void) const;

	bool InitializeInProgress()
	{
		return m_bInitializeRunning;
	};

	//handles the actual processing of the focus.
	//	called by setFocus after event firing, suitability
	//	and cancellation have occured.
	virtual HRESULT showFocus();

protected:
	virtual ~CFormControl();

	virtual HRESULT formControlInitialize();
	CComBSTR m_sAccessKey;
	CComBSTR m_sNavIndex;
	BOOL m_bIncremental;
	//to hold an explicit navindex property.
	// unsigned long m_ulNavIndex;
	BOOL m_bUIConstructed; //this can be removed.
	bool m_bLateInitalise;
	
	void FireStateEvents();
	virtual bool IsAppropriateToInitializeNow();
	virtual HRESULT doInitialize();
	
	// checks whether focus can be recieved or passed on
	//	by this control, and whether the focus event  
	//	default processing is cancelled by custom handling.
	virtual bool receiveFocus();
	virtual void onBindToNothing();

	// Moved to CFormControl as part of bug 459.
	CComBSTR m_sControlType;
private:

	CComBSTR m_sParentId;
	CComBSTR m_sParentModel;
	CComBSTR m_sParentNodeset;
	CComBSTR m_sParentRef;
	ULONG m_ulParentOffset;
	bool m_bControlInRange;
	
	//postponed state event handling.
	HRESULT SignalEvent(long lState,bool bValue);
	long m_lState;
	bool m_bValueChanged;
	bool m_bStateChanged;
	bool m_bInitializeRunning;

};

inline bool CFormControl::isLateInitalisedControl() {
	return m_bLateInitalise;
}

inline HRESULT CFormControl::initialize(bool bForce)
{
	HRESULT hr = S_FALSE;
/*	if((bForce || !m_bInitializeDone) && SUCCEEDED(hr = doInitialize()))
		m_bInitializeDone = true;
*/
	if(bForce || (!m_bInitializeDone && !m_bInitializeRunning ))
	{
		m_bInitializeRunning = true;
		if(IsAppropriateToInitializeNow())
			hr = doInitialize();
		m_bInitializeRunning = false;
		if(hr == S_OK)
			m_bInitializeDone = true;
	}
	return hr;
}

inline HRESULT CFormControl::getNavIndex(BSTR * pszVal)
{
	return m_sNavIndex.CopyTo(pszVal);
}

inline HRESULT CFormControl::getAccessKey(BSTR * pszVal)
{
	return m_sAccessKey.CopyTo(pszVal);
}

inline HRESULT CFormControl::getIncremental(BOOL * pszIncremental)
{
	*pszIncremental = m_bIncremental;

	return S_OK;
}

inline BSTR CFormControl::GetControlType(void) const
{
	return m_sControlType.m_str;
}

inline bool CFormControl::InRange(void) const
{
	return m_bControlInRange;
}

#endif // !defined(AFX_FORMCONTROL_H__81D997E7_782B_4D83_95B2_34EA58BEFA7E__INCLUDED_)